package com.atguigu.tingshu.search.service.impl;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.FieldValue;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.NestedQuery;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.CompletionSuggest;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.elasticsearch.core.search.Suggestion;
import com.alibaba.fastjson.JSON;
import com.atguigu.tingshu.album.client.AlbumInfoFeignClient;
import com.atguigu.tingshu.album.client.CategoryFeignClient;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.util.PinYinUtils;
import com.atguigu.tingshu.model.album.*;
import com.atguigu.tingshu.model.search.AlbumInfoIndex;
import com.atguigu.tingshu.model.search.AttributeValueIndex;
import com.atguigu.tingshu.model.search.SuggestIndex;
import com.atguigu.tingshu.query.search.AlbumIndexQuery;
import com.atguigu.tingshu.search.repository.SuggestIndexRepository;
import com.atguigu.tingshu.search.service.SearchService;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.album.AlbumStatVo;
import com.atguigu.tingshu.vo.search.AlbumInfoIndexVo;
import com.atguigu.tingshu.vo.search.AlbumSearchResponseVo;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.data.elasticsearch.core.suggest.Completion;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;


@Slf4j
@Service
@SuppressWarnings({"all"})
public class SearchServiceImpl implements SearchService {

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;
    @Autowired
    private AlbumInfoFeignClient albuminfoFeiginClient;
    @Autowired
    private UserInfoFeignClient userInfoFeignClient;
    @Autowired
    private CategoryFeignClient categoryFeignClient;
    @Autowired
    private AlbumInfoRespository albumInfoRepository;
    @Autowired
    private ElasticsearchClient elasticsearchClient;
    @Autowired
    private SuggestIndexRepository suggestIndexRepository;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RedissonClient redissonClient;


    /**
     * 更新专辑信息到索引
     * <p>
     * 此方法负责从多个远程服务获取专辑（Album）相关信息，并将其整合到专辑索引（AlbumInfoIndex）对象中，
     * 最终保存到数据库中这个过程涉及多次远程调用、数据转换和属性拷贝，目的是为了保持专辑信息的最新状态，
     * 并便于后续的查询和使用
     *
     * @param albumId 专辑ID，用于标识和获取特定的专辑信息
     */
    @Override
    public void  upperAlbum(Long albumId) {
        // 新建一个对象
        AlbumInfoIndex albumInfoIndex = new AlbumInfoIndex();
        CompletableFuture<AlbumInfo> albumInfoCompletableFuture = CompletableFuture.supplyAsync(() -> {
            // 根据albumId远程调用获取albumInfo数据
            Result<AlbumInfo> albumInfdo = albuminfoFeiginClient.getAlbumInfo(albumId);
            // 调用Assert方法去判断远程调用结果是否为空,如果为空就抛出异常,异常信息为message中的信息
            Assert.notNull(albumInfdo, "远程获取albumInfo数据失败");
            // 从result中取出返回的信息
            AlbumInfo albumInfo = albumInfdo.getData();
            // 进行属性拷贝
            BeanUtils.copyProperties(albumInfo, albumInfoIndex);
            return albumInfo;
        }, threadPoolExecutor);
        CompletableFuture<Void> userInfoVoCompletableFuture = albumInfoCompletableFuture.thenAcceptAsync(albumInfo -> {
            // 根据albumInfo中的用户id远程调用获取到用户信息
            Result<UserInfoVo> userInfoVo = userInfoFeignClient.getUserInfoVo(albumInfo.getUserId());
            Assert.notNull(userInfoVo, "远程获取用户信息失败");
            UserInfoVo data = userInfoVo.getData();
            albumInfoIndex.setAnnouncerName(data.getNickname());
        }, threadPoolExecutor);
        CompletableFuture<Void> baseCategoryViewCompletableFuture = albumInfoCompletableFuture.thenAcceptAsync(albumInfo -> {
            // 远程调用获取分类信息
            Result<BaseCategoryView> categoryInfo = categoryFeignClient.getCategoryInfo(albumInfo.getCategory3Id());
            Assert.notNull(categoryInfo, "远程获取分类信息失败");
            BaseCategoryView data1 = categoryInfo.getData();
            BeanUtils.copyProperties(data1, albumInfoIndex);
        }, threadPoolExecutor);
        CompletableFuture<Void> AttributeValueCompletableFuture = albumInfoCompletableFuture.thenAcceptAsync(albumInfo -> {
            // 处理专辑属性值列表
            List<AlbumAttributeValue> albumAttributeValueVoList = albumInfo.getAlbumAttributeValueVoList();
            List<AttributeValueIndex> collect = albumAttributeValueVoList.stream().map(albumAttributeValue -> {
                AttributeValueIndex attributeValueIndex = new AttributeValueIndex();
                BeanUtils.copyProperties(albumAttributeValue, attributeValueIndex);
                return attributeValueIndex;
            }).collect(Collectors.toList());
            albumInfoIndex.setAttributeValueIndexList(collect);
        }, threadPoolExecutor);
        CompletableFuture<Void> voidCompletableFuture = albumInfoCompletableFuture.thenAcceptAsync((albumInfo) -> {
            // 远程调用获取专辑统计信息
            Result<AlbumStatVo> albumStat = albuminfoFeiginClient.getAlbumStat(albumId);
            Assert.notNull(albumStat, "远程获取albumStat数据失败");
            AlbumStatVo data2 = albumStat.getData();
            BeanUtils.copyProperties(data2, albumInfoIndex);
            // 设置热度得分
            albumInfoIndex.setHotScore((double) new Random().nextInt(1000000));
        }, threadPoolExecutor);

//        CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {
//            // 远程调用获取专辑统计信息
//            Result<AlbumStatVo> albumStat = albuminfoFeiginClient.getAlbumStat(albumId);
//            Assert.notNull(albumStat, "远程获取albumStat数据失败");
//            AlbumStatVo data2 = albumStat.getData();
//            BeanUtils.copyProperties(data2, albumInfoIndex);
//            // 设置热度得分
//            albumInfoIndex.setHotScore((double) new Random().nextInt(1000000));
//        }, threadPoolExecutor);
        CompletableFuture.allOf(userInfoVoCompletableFuture,
                baseCategoryViewCompletableFuture,
                AttributeValueCompletableFuture,
                voidCompletableFuture).join();
//        重新给albuminfoindex设置id，id为albumId
        albumInfoIndex.setId(albumId);

        // 保存专辑信息到索引库
        albumInfoRepository.save(albumInfoIndex);
        //  上架添加提词数据.
//  创建对象 专辑标题提词
        SuggestIndex suggestIndex = new SuggestIndex();
        suggestIndex.setId(UUID.randomUUID().toString().replaceAll("-", ""));
        suggestIndex.setTitle(albumInfoIndex.getAlbumTitle());
        suggestIndex.setKeyword(new Completion(new String[]{albumInfoIndex.getAlbumTitle()}));
        suggestIndex.setKeywordPinyin(new Completion(new String[]{PinYinUtils.toHanyuPinyin(albumInfoIndex.getAlbumTitle())}));
        suggestIndex.setKeywordSequence(new Completion(new String[]{PinYinUtils.getFirstLetter(albumInfoIndex.getAlbumTitle())}));
        this.suggestIndexRepository.save(suggestIndex);

//  专辑简介提词
        SuggestIndex albumIntroSuggestIndex = new SuggestIndex();
        albumIntroSuggestIndex.setId(UUID.randomUUID().toString().replaceAll("-", ""));
        albumIntroSuggestIndex.setTitle(albumInfoIndex.getAlbumIntro());
        albumIntroSuggestIndex.setKeyword(new Completion(new String[]{albumInfoIndex.getAlbumIntro()}));
        albumIntroSuggestIndex.setKeywordPinyin(new Completion(new String[]{PinYinUtils.toHanyuPinyin(albumInfoIndex.getAlbumIntro())}));
        albumIntroSuggestIndex.setKeywordSequence(new Completion(new String[]{PinYinUtils.getFirstLetter(albumInfoIndex.getAlbumIntro())}));
        this.suggestIndexRepository.save(albumIntroSuggestIndex);

// 专辑主播提词
        SuggestIndex announcerSuggestIndex = new SuggestIndex();
        announcerSuggestIndex.setId(UUID.randomUUID().toString().replaceAll("-", ""));
        announcerSuggestIndex.setTitle(albumInfoIndex.getAnnouncerName());
        announcerSuggestIndex.setKeyword(new Completion(new String[]{albumInfoIndex.getAnnouncerName()}));
        announcerSuggestIndex.setKeywordPinyin(new Completion(new String[]{PinYinUtils.toHanyuPinyin(albumInfoIndex.getAnnouncerName())}));
        announcerSuggestIndex.setKeywordSequence(new Completion(new String[]{PinYinUtils.getFirstLetter(albumInfoIndex.getAnnouncerName())}));
        suggestIndexRepository.save(announcerSuggestIndex);



    }


    /**
     * 根据相册ID删除相册信息
     * 此方法通过调用albumInfoRepository的deleteById方法来实现相册的删除操作
     * 主要用于在系统中移除不再需要或存在错误的相册信息
     *
     * @param albumId 相册的唯一标识符，用于定位并删除特定的相册信息
     */
    @Override
    public void lowerAlbum(Long albumId) {
        albumInfoRepository.deleteById(albumId);
    }

    @Override
    public AlbumSearchResponseVo search(AlbumIndexQuery albumIndexQuery) {
//        开发步骤 1.先编写DSL语句 2.从DSL中动态获取数据 3.封装数据并且返回
//        创建一个返回的对象
        AlbumSearchResponseVo albumSearchResponseVo = new AlbumSearchResponseVo();
//      调用方法,封装SearchRequest信息并且返回
        SearchRequest searchRequest = createSearchRequest(albumIndexQuery);
//        创建查询客户端对象
        SearchResponse<AlbumInfoIndex> response = null;
        try {
            response = elasticsearchClient.search(searchRequest, AlbumInfoIndex.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
//        获取到对应的数据,并且赋值
        albumSearchResponseVo.setTotal(response.hits().total().value());
        albumSearchResponseVo.setPageNo(albumIndexQuery.getPageNo());
        albumSearchResponseVo.setPageSize(albumIndexQuery.getPageSize());
        albumSearchResponseVo.setTotalPages((Long) (albumSearchResponseVo.getTotal() / albumIndexQuery.getPageSize() + 1));
        List<Hit<AlbumInfoIndex>> hits = response.hits().hits();
        List<AlbumInfoIndexVo> albumInfoIndexVoList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(hits)) {
            hits.stream().forEach(hit -> {
                AlbumInfoIndexVo albumInfoIndexVo = new AlbumInfoIndexVo();
                AlbumInfoIndex albumInfoIndex = hit.source();
                BeanUtils.copyProperties(albumInfoIndex, albumInfoIndexVo);
                Map<String, List<String>> highlight = hit.highlight();
                if (highlight.get("albumTitle") != null) {
                    String s = highlight.get("albumTitle").get(0);
                    albumInfoIndexVo.setAlbumTitle(s);
                }
                albumInfoIndexVoList.add(albumInfoIndexVo);
            });
        }
//        if(!CollectionUtils.isEmpty(hits)){
//            List<AlbumInfoIndexVo> albumInfoIndexVoList = hits.stream().map(hit -> {
//                AlbumInfoIndexVo albumInfoIndexVo = new AlbumInfoIndexVo();
//                AlbumInfoIndex albumInfoIndex = hit.source();
//                BeanUtils.copyProperties(albumInfoIndex, albumInfoIndexVo);
//                Map<String, List<String>> highlight = hit.highlight();
//                if (highlight != null) {
//                    String s = highlight.get("albumTitle").get(0);
//                    albumInfoIndexVo.setAlbumTitle(s);
//                }
//                return albumInfoIndexVo;
//            }).collect(Collectors.toList());
        //        将其添加到albumSearchResponseVo中
//        }
        albumSearchResponseVo.setList(albumInfoIndexVoList);
// 将执行的代码输出到控制台上
        System.out.println("dsl:\t" + searchRequest.toString());
        return albumSearchResponseVo;
    }

    private SearchRequest createSearchRequest(AlbumIndexQuery albumIndexQuery) {
        //        创建查询请求对象,先创建SearchBuilder.Builder对象
        SearchRequest.Builder searchRequestBuilder = new SearchRequest.Builder();
//        创建BoolQueryBuilder对象
        BoolQuery.Builder boolQueryBuilder = new BoolQuery.Builder();
//        判断AlbumIndexQuery 中的关键字是否为空
        if (!ObjectUtils.isEmpty(albumIndexQuery.getKeyword())) {
//            如果不为空就添加数据
            boolQueryBuilder.should(s -> s.match(m -> m.field("albumIntro").query(albumIndexQuery.getKeyword())));
            boolQueryBuilder.should(s -> s.match(m -> m.field("albumName").query(albumIndexQuery.getKeyword())));
            boolQueryBuilder.should(s -> s.match(m -> m.field("announcerName").query(albumIndexQuery.getKeyword())));
        }
//        判断albumIndexQuery中的分类id是否为空
        if (!ObjectUtils.isEmpty(albumIndexQuery.getCategory1Id())) {
//            如果不为空就添加数据
            boolQueryBuilder.must(s -> s.term(t -> t.field("category1Id").value(albumIndexQuery.getCategory1Id())));
        }
        if (!ObjectUtils.isEmpty(albumIndexQuery.getCategory2Id())) {
//            如果不为空就添加数据
            boolQueryBuilder.must(s -> s.term(t -> t.field("category2Id").value(albumIndexQuery.getCategory2Id())));
        }
        if (!ObjectUtils.isEmpty(albumIndexQuery.getCategory3Id())) {
//            如果不为空就添加数据
            boolQueryBuilder.must(s -> s.term(t -> t.field("category3Id").value(albumIndexQuery.getCategory3Id())));
        }

//        判断属性和属性值是否为空
        if (!ObjectUtils.isEmpty(albumIndexQuery.getAttributeList())) {
            List<String> attributeList = albumIndexQuery.getAttributeList();
//            遍历attributeList集合中的数据
            for (String s : attributeList) {
//                去分割字符串得到里面的数据
                String[] split = s.split(":");
                if (split.length == 2 && split != null) {
//                   创建一个NestedQueryBuilder对象
                    NestedQuery.Builder nestedQueryBuilder = new NestedQuery.Builder();
//                    给NestedQueryBuilder对象设置属性
                    nestedQueryBuilder.path("attributeValueIndexList").query(q -> q.bool(f1 -> f1.filter(b -> b.match(m -> m.field("attributeValueIndexList.attributeId").query(split[0]))))).query(b1 -> b1.match(m1 -> m1.field("attributeValueIndexList.attributeValueId").query(split[1])));
//                    通过NestedQueryBuilder对象创建NestedQuery对象
                    NestedQuery nestedQuery = nestedQueryBuilder.build();
//                    添加到boolQueryBuilder对象中
                    boolQueryBuilder.filter(f -> f.nested(nestedQuery));
                }
            }
//            设置排序字段
            if (!ObjectUtils.isEmpty(albumIndexQuery.getOrder())) {
                String order = albumIndexQuery.getOrder();
                String[] split = order.split(":");
                switch (split[0]) {
                    case "1":
                        searchRequestBuilder.sort(s -> s.field(f -> f.field("hotScore").order(split[1] == "0" ? SortOrder.Asc : SortOrder.Desc)));
                        break;
                    case "2":
                        searchRequestBuilder.sort(s -> s.field(f -> f.field("playStatNum").order(split[1] == "0" ? SortOrder.Asc : SortOrder.Desc)));
                        break;
                    case "3":
                        searchRequestBuilder.sort(s -> s.field(f -> f.field("createTime").order(split[1] == "0" ? SortOrder.Asc : SortOrder.Desc)));
                }
            }
        }
//        设置起始页数
        searchRequestBuilder.from((albumIndexQuery.getPageNo() - 1) * albumIndexQuery.getPageSize());
//        设置每页多少数目
        searchRequestBuilder.size(albumIndexQuery.getPageSize());
//        根据boolQueryBuilder获取到boolQuery对象
        BoolQuery boolQuery = boolQueryBuilder.build();
//        跟去SearchRequestBuilder的方法设置索引表,并设置query属性
        searchRequestBuilder.index("albuminfo").query(q -> q.bool(boolQuery));
//        再根据SearchRequest.Builder的builder的方法创建SearchRequest对象   这种创建方式叫构建者模式
        SearchRequest searchRequest = searchRequestBuilder.build();

        //        将其返回
        return searchRequest;
    }

    @Override
    public List<Map<String, Object>> channel(Long category1Id) {
//        远程调用根据一级分类的id获取到三级分类数据
        Result<List<BaseCategory3>> topBaseCategory3 = categoryFeignClient.findTopBaseCategory3(category1Id);
//        判断数据是否为空
        Assert.notNull(topBaseCategory3, "远程调用失败");
//        取出对应的数据信息
        List<BaseCategory3> category3s = topBaseCategory3.getData();
//        判断数据是否为空
        Assert.notNull(category3s, "远程调用失败");
//        建立对应的关系
        Map<Long, BaseCategory3> baseCategory3Map = category3s.stream().collect(Collectors.toMap(baseCategory3 -> baseCategory3.getId(), baseCategory3 -> baseCategory3));
//         如果不为空的话就获取到对应的category3Id集合
        List<FieldValue> collect = category3s.stream().map(category3sId -> FieldValue.of(category3sId.getId())).collect(Collectors.toList());
//        根据category3Id集合从es中获取
        SearchRequest.Builder searchRequestBuilder = new SearchRequest.Builder();
        searchRequestBuilder.index("albuminfo")
                .query(q -> q.terms(t -> t.field("category3Id").terms(t1 -> t1.value(collect))))
                .aggregations("groupByCategory3IdAgg", a -> a.terms(t -> t.field("category3Id").size(10))
                        .aggregations("topTenHotScoreAgg", a1 -> a1.topHits(t2 -> t2.size(6).sort(s -> s.field(f -> f.field("hotScore").order(SortOrder.Desc)))))
                );
//        获取对应的SearchRequest对象
        SearchRequest searchRequest = searchRequestBuilder.build();
//        获取对应的SearchResponse对象
        SearchResponse<Map> resp = null;
        try {
            resp = elasticsearchClient.search(searchRequest, Map.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
//        定义一个list用来存放返回的map集合
        List<Map<String, Object>> maps = new ArrayList<>();
//        去获取对应的数据
        resp.aggregations()
                .get("groupByCategory3IdAgg").lterms().buckets().array().stream().forEach(b -> {
//                    生成一个集合,用于存储三级分类id下的全部专辑信息
                    List<AlbumInfoIndex> list = new ArrayList<>();
//                    将三级分类id取出来,用于查询三级分类id的数据做准备
                    long key = b.key();
//                    取出三级分类name数据下的所有专辑
                    b.aggregations().get("topTenHotScoreAgg").topHits().hits().hits().forEach(h -> {
//                        将对应的专辑转化为jsonString
                        String jsonString = h.source().toString();
//                        再将json转化为对应的Object实体类
                        AlbumInfoIndex albumInfoIndex = JSON.parseObject(jsonString, AlbumInfoIndex.class);
//                        将对象添加到对应的list中
                        list.add(albumInfoIndex);
                    });
//                    生成一个map集合
                    HashMap<String, Object> map = new HashMap<>();
//                    将通过key查找到的数据封装到对应的key上
                    map.put("baseCategory3", baseCategory3Map.get(key));
//                    将三级分类下的专辑列表数据添加到对应的map中
                    map.put("list", list);
                    maps.add(map);
                });
//        将数据进行返回
        return maps;
    }

    @Override
    public List<String> completeSuggest(String keyword) {
//  Java 动态生成dsl 语句.
        SearchRequest.Builder searchRequest = new SearchRequest.Builder();
        searchRequest.index("suggestinfo").suggest(
                s -> s.suggesters("suggestionKeyword", f -> f.prefix(keyword).completion(
                                c -> c.field("keyword").skipDuplicates(true).size(10)
                                        .fuzzy(
                                                z -> z.fuzziness("auto"))
                        ))
                        .suggesters("suggestionkeywordPinyin", f -> f.prefix(keyword).completion(
                                c -> c.field("keywordPinyin").skipDuplicates(true).size(10)
                                        .fuzzy(z -> z.fuzziness("auto"))
                        ))
                        .suggesters("suggestionkeywordSequence", f -> f.prefix(keyword).completion(
                                c -> c.field("keywordSequence").skipDuplicates(true).size(10)
                                        .fuzzy(z -> z.fuzziness("auto"))
                        ))
        );
        //  获取查询结果
        SearchResponse<SuggestIndex> searchResponse = null;
        try {
            searchResponse = elasticsearchClient.search(searchRequest.build(), SuggestIndex.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        //  获取到结果集,数据转换. set集合无序不重复? 1.hashCode(); 2.equals();   为什么 底层hashMap !map.key=value map.value=new Object();
        HashSet<String> titleSet = new HashSet<>();
        titleSet.addAll(this.parseResultData(searchResponse, "suggestionKeyword"));
        titleSet.addAll(this.parseResultData(searchResponse, "suggestionkeywordPinyin"));
        titleSet.addAll(this.parseResultData(searchResponse, "suggestionkeywordSequence"));


        //  返回数据
        return new ArrayList<>(titleSet);
    }

    /**
     * 处理聚合结果集
     *
     * @param response
     * @param suggestName
     * @return
     */
    private List<String> parseResultData(SearchResponse<SuggestIndex> response, String suggestName) {
        //  创建集合
        List<String> suggestList = new ArrayList<>();
        Map<String, List<Suggestion<SuggestIndex>>> groupBySuggestionListAggMap = response.suggest();
        groupBySuggestionListAggMap.get(suggestName).forEach(item -> {
            CompletionSuggest<SuggestIndex> completionSuggest = item.completion();
            completionSuggest.options().forEach(it -> {
                SuggestIndex suggestIndex = it.source();
                suggestList.add(suggestIndex.getTitle());
            });
        });
        //  返回集合列表
        return suggestList;
    }

    /**
     * 根据一级分类ID和统计类型查找排名列表
     *
     * @param cartgory1Id 一级分类ID
     * @param statType    统计类型
     */
    @Override
    public void updateLatelyAlbumRanking() {
        // 先远程调用获取一级分类id
        Result<List<BaseCategory1>> allCategory1 = categoryFeignClient.findAllCategory1();
        // 断言获取一级分类数据不为空
        Assert.notNull(allCategory1, "远程调用获取一级分类失败");
        List<BaseCategory1> baseCategory1List = allCategory1.getData();
        // 再次断言确保一级分类数据列表不为空
        Assert.notNull(baseCategory1List, "远程调用获取一级分类失败");
        // 遍历一级分类列表
        for (BaseCategory1 baseCategory1 : baseCategory1List) {
            // 生成一个数组，里面存放排行的条件
            String[] strings = {"hotScore", "playStatNum", "subscribeStatNum", "buyStatNum", "commentStatNum"};
            // 遍历排行条件数组
            for (String string : strings) {
                // 先从es中查询数据，定义searchRequest
                SearchRequest.Builder searchRequestBuilder = new SearchRequest.Builder();
                // 去设置条件
                searchRequestBuilder.index("albuminfo").query(q -> q.term(t -> t.field("category1Id").value(baseCategory1.getId())))
                        .sort(s -> s.field(d -> d.field(string).order(SortOrder.Desc)))
                        .size(10);
                // 执行ES查询
                try {
                    SearchResponse<AlbumInfoIndex> response = elasticsearchClient.search(searchRequestBuilder.build(), AlbumInfoIndex.class);
                    // 处理查询结果，转换为列表
                    List<AlbumInfoIndex> collect = response.hits().hits().stream().map(h -> h.source()).collect(Collectors.toList());
                    // 构造Redis键值
                    String redisKey = RedisConstant.RANKING_KEY_PREFIX + baseCategory1.getId();
                    // 将排行数据存入Redis
                    redisTemplate.boundHashOps(redisKey).put(string, collect);
                } catch (IOException e) {
                    // 捕获异常并抛出运行时异常
                    throw new RuntimeException(e);
                }
            }
        }
    }

    /**
     * 根据一级分类ID和统计类型查找排名列表
     *
     * @param category1Id 一级分类ID，用于指定分类
     * @param statType 统计类型，用于指定想要查找的排名列表类型
     * @return 返回指定分类和统计类型的排名列表，列表中包含专辑索引信息
     *
     * 本方法首先根据一级分类ID构建Redis键，然后从Redis中获取对应统计类型的排名列表
     * 使用缓存来提高查询效率，避免频繁访问数据库
     */
    @Override
    public List<AlbumInfoIndex> findRankingList(Long category1Id, String statType) {
        // 构建Redis键，结合一级分类ID以获取特定分类的排名信息
        String redisKey = RedisConstant.RANKING_KEY_PREFIX + category1Id;

        // 从Redis中获取指定统计类型的排名列表，结果转换为List<AlbumInfoIndex>类型返回
        return (List<AlbumInfoIndex>) redisTemplate.boundHashOps(redisKey).get(statType);
    }
}
